﻿/*========================== 
 * @author 郑金泉
 * @desc 前端实用工具
 * ========================= */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Net;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;

using Newtonsoft.Json;

namespace Obsidian.Utils
{
    public class WebUtil
    {
        /// <summary>
        /// 移除所有html标签
        /// </summary>
        /// <param name="htmlString"></param>
        /// <returns></returns>
        public static string RemoveAllHtmlTag(string htmlString)
        {
            //删除脚本 
            htmlString = Regex.Replace(htmlString, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            //删除HTML 
            htmlString = Regex.Replace(htmlString, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"-->", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"<!--.*", "", RegexOptions.IgnoreCase);

            htmlString = Regex.Replace(htmlString, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(nbsp|#160);", "   ", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&#(\d+);", "", RegexOptions.IgnoreCase);

            htmlString.Replace("<", "");
            htmlString.Replace(">", "");
            //htmlString.Replace("\r\n", "");
            htmlString = htmlString.Trim();

            return htmlString;
        }

        /// <summary>
        /// 过滤HTML标签，只保留img，并替换br为\r\n
        /// </summary>
        /// <param name="htmlText"></param>
        /// <returns></returns>
        public static string ReplaceHtmlTage(string htmlText)
        {
            htmlText = htmlText.Trim();
            htmlText = htmlText.Replace(@"</p>", "\r\n");
            htmlText = htmlText.Replace(@"<br>", "\r\n");//将HTML换行转为\r\n 
            htmlText = htmlText.Replace(@"<br/>", "\r\n");
            htmlText = Regex.Replace(htmlText, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"(?i)<(?!img|br)[^>]*>", "", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(nbsp|#160);", "   ", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            htmlText = Regex.Replace(htmlText, @"&#(\d+);", "", RegexOptions.IgnoreCase);
            return htmlText;
        }

        public static string HtmlToText(string html)
        {
            string result = html.Replace("&", "&amp;");
            result = result.Replace("'", "&apos;");
            result = result.Replace("\"", "&quot;");
            result = result.Replace(">", "&gt;");
            result = result.Replace("<", "&lt;");
            result = result.Replace(" ", "&nbsp;");
            result = result.Replace("&", "&amp;");
            result = result.Replace("\"", "&quot;");
            return result;
        }

        public static string TextToHtml(string text)
        {
            string result = text.Replace("&lt;", "<");
            result = result.Replace("&gt;", ">");
            result = result.Replace("    ", "\t");
            result = result.Replace("<br/>", "\n");
            result = result.Replace("&nbsp;", " ");
            result = result.Replace("&amp;", "&");
            result = result.Replace("&quot;", "\"");
            return result;
        }

        public static bool IsUrlExists(string url)
        {
            if (!url.Contains("http://") && !url.Contains("https://"))
            {
                url = "http://" + url;
            }
            try
            {
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
                myRequest.Method = "HEAD";
                myRequest.Timeout = 10000;  //超时时间10秒
                HttpWebResponse res = (HttpWebResponse)myRequest.GetResponse();
                bool isExists = res.StatusCode == HttpStatusCode.OK;
                res.Close();
                return isExists;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 高亮显示关键字
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="keyword">关键字</param>
        /// <param name="color">颜色(十六进制字符串)</param>
        /// <returns></returns>
        public static string HighlightKeyword(string str, string keyword, string color)
        {
            int index;
            int startIndex = 0;
            string highlightBegin = "<span style=\"color:" + color + "\">";
            string highlightEnd = "</span>";
            int length = highlightBegin.Length + keyword.Length;
            int lengthHighlight = length + highlightEnd.Length;

            while ((index = str.IndexOf(keyword, startIndex, StringComparison.OrdinalIgnoreCase)) > -1)
            {
                str = str.Insert(index, highlightBegin).Insert(index + length, highlightEnd);
                startIndex = index + lengthHighlight;
            }

            return str;
        }

        /// <summary>
        /// 获取字符串中的模板
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="templName">模板标识名</param>
        /// <example>
        /// 模板格式：<!-- #templ[templName] -->模板内容....<!-- #templ[templName] end -->
        /// </example>
        /// <returns></returns>
        public static string GetTemplString(string str, string templName)
        {
            string result = null;
            string pattern = @"<!--(\s+)#templ\[" + templName + @"\](\s+)-->(?<result>[\s\S]*?)<!--(\s+)#templ\[" + templName + @"\](\s+)end(\s+)-->";
            Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
            Match m = regex.Match(str);
            if (m.Success)
            {
                result = m.Groups["result"].Value;
            }
            return result;
        }

        /// <summary>
        /// 替换字符串模板
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="templName">模板标识名</param>
        /// <param name="newStr">替换字符串</param>
        /// <example>
        /// 模板格式：<!-- #templ[templName] -->模板内容....<!-- #templ[templName] end -->
        /// </example>   
        /// <returns>结果</returns>
        public static string ReplaceTemplTag(string str, string templName, string newStr)
        {
            string pattern = @"<!--(\s+)#templ\[" + templName + @"\](\s+)-->[\s\S]*<!--(\s+)#templ\[" + templName + @"\](\s+)end(\s+)-->";
            string result = Regex.Replace(str, pattern, newStr);
            return result;
        }

        /// <summary>
        /// 生成重写URL
        /// </summary>
        /// <returns></returns>
        public static string Rewrite(string page, params object[] parameters)
        {
            StringBuilder sb = new StringBuilder(page);
            foreach (object p in parameters)
                sb.Append("-" + p.ToString().Trim());
            sb.Append(".html");
            return sb.ToString();
        }

        /// <summary>
        /// URL编码
        /// </summary>
        /// <param name="str">原字符</param>
        /// <param name="encodingName">编码名称</param>
        /// <returns>结果字符</returns>
        public static string UrlEncode(string str, string encodingName)
        {
            byte[] bs = Encoding.GetEncoding(encodingName).GetBytes(str);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bs.Length; i++)
            {
                if (bs[i] < 128)
                    sb.Append((char)bs[i]);
                else
                {
                    sb.Append("%" + bs[i++].ToString("x").PadLeft(2, '0'));
                    sb.Append("%" + bs[i].ToString("x").PadLeft(2, '0'));
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 在页面输出图片
        /// </summary>
        /// <param name="bitmap"></param>
        public static void DrawImage(Bitmap bitmap)
        {
            MemoryStream ms = new MemoryStream();
            HttpResponse response = HttpContext.Current.Response;
            bitmap.Save(ms, ImageFormat.Jpeg);
            response.ClearContent();
            response.ContentType = "image/Jpeg";
            response.BinaryWrite(ms.GetBuffer());
            ms.Close();
            ms = null;
            bitmap.Dispose();
            bitmap = null;
            response.End();
        }

        public static void WriteJsonString(object obj)
        {
            HttpResponse response = HttpContext.Current.Response;
            response.Write(JsonConvert.SerializeObject(obj));
        }

        public static void IncludeJs(Page page, params string[] jsfiles)
        {
            IncludeJs(page, false, jsfiles);
        }


        public static void IncludeJs(Page page, bool withTime, params string[] jsfiles)
        {
            string src = "";
            foreach (string f in jsfiles)
            {
                if (withTime && f.IndexOf("http://") != 0)
                {
                    string path = HttpContext.Current.Server.MapPath(f);
                    FileInfo file = new FileInfo(path);
                    string updateTime = file.LastWriteTime.ToString("mmss");
                    src = f + "?t=" + updateTime;
                }
                else
                {
                    src = f;
                }
                HtmlGenericControl script = new HtmlGenericControl();
                script.TagName = "script";
                script.Attributes.Add("langugae", "javascript");
                script.Attributes.Add("type", "text/javascript");
                script.Attributes.Add("src", src);
                page.Header.Controls.Add(script);
            }
        }

        private const string JS_INCLUDE_HTML = "<script src=\"{0}\" type=\"text/javascript\" langugae=\"javascript\"></script>";
        public static string IncludeJsHtml(string jsFiles)
        {
            StringBuilder sb = new StringBuilder();
            string[] arrFiles = jsFiles.Split(',');
            foreach (string f in arrFiles)
            {
                string src;
                if (f.IndexOf("http://") != 0)
                {
                    string path = MapPath(f);
                    FileInfo file = new FileInfo(path);
                    string updateTime = file.LastWriteTime.ToString("mmss");
                    src = f + "?t=" + updateTime;
                }
                else
                {
                    src = f;
                }
                sb.Append(String.Format(JS_INCLUDE_HTML, src));
            }
            return sb.ToString();
        }

        public static void IncludeCss(Page page, params string[] cssfiles)
        {
            IncludeCss(page, false, cssfiles);
        }

        public static void IncludeCss(Page page, bool withTime, params string[] cssfiles)
        {
            string href = "";
            foreach (string f in cssfiles)
            {
                if (withTime && f.IndexOf("http://") != 0)
                {
                    string path = HttpContext.Current.Server.MapPath(f);
                    FileInfo file = new FileInfo(path);
                    string updateTime = file.LastWriteTime.ToString("mmss");
                    href = f + "?t=" + updateTime;
                }
                else
                {
                    href = f;
                }
                HtmlLink link = new HtmlLink();
                link.Attributes.Add("rel", "stylesheet");
                link.Attributes.Add("type", "text/css");
                link.Attributes.Add("href", href);
                page.Header.Controls.Add(link);
            }
        }

        private const string CSS_INCLUDE_HTML = "<link href=\"{0}\" type=\"text/css\" rel=\"stylesheet\">";
        public static string IncludeCssHtml(string cssFiles)
        {
            StringBuilder sb = new StringBuilder();
            string[] arrFiles = cssFiles.Split(',');
            foreach (string f in arrFiles)
            {
                string href;
                if (f.IndexOf("http://") != 0)
                {
                    string path = HttpContext.Current.Server.MapPath(f);
                    FileInfo file = new FileInfo(path);
                    string updateTime = file.LastWriteTime.ToString("mmss");
                    href = f + "?t=" + updateTime;
                }
                else
                {
                    href = f;
                }
                sb.Append(String.Format(CSS_INCLUDE_HTML, href));
            }
            return sb.ToString();
        }

        public static string CreateUrl(string path, Dictionary<string, object> prms)
        {
            StringBuilder sb = new StringBuilder(path);
            if (prms != null && prms.Count > 0)
            {
                int queryIndex = path.IndexOf("?");
                if (queryIndex == -1)
                    sb.Append("?");
                else if (queryIndex < path.Length - 1)
                    sb.Append("&");
                foreach (string key in prms.Keys)
                    sb.Append(key + "=" + HttpUtility.UrlEncode(prms[key].ToString()) + "&");
                sb.Remove(sb.Length - 1, 1);
            }
            return sb.ToString();
        }

        public static string MapPath(string path)
        {
            return HttpContext.Current.Server.MapPath(path);
        }

        public static Bitmap GetBitmap(string url)
        {
            try
            {
                // create a web request to the url of the image
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                // set the method to GET to get the image
                request.Method = "GET";
                // get the response from the webpage
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                // create a bitmap from the stream of the response
                Bitmap bmp = new Bitmap(response.GetResponseStream());
                // close off the stream and the response
                response.Close();
                // return the Bitmap of the image
                return bmp;
            }
            catch (Exception ex)
            {
                return null; // if for some reason we couldn't get to image, we return null
            }
        }

        public static string GetCurrentHost()
        {
            string url = HttpContext.Current.Request.Url.ToString();
            return GetHost(url);
        }

        public static string GetHost(string url)
        {
            if (String.IsNullOrEmpty(url))
                return url;
            string http = "http://";
            int n = url.IndexOf(http);
            if (n == 0)
                url = url.Substring(http.Length);
            n = url.IndexOf("/");
            return n > 0 ? url.Substring(0, n) : url;
        }

        public static bool IsIPAddress(string str)
        {
            if (string.IsNullOrEmpty(str) || str.Length < 7 || str.Length > 15)
                return false;

            string regformat = @"^(\d{1,3}\.){3}\d{1,3}\:\d{1,5}$"; //@"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}{1}&";
            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);
            return regex.IsMatch(str);
        }

        public static string GetRealIP()
        {
            string result = String.Empty;

            result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            //可能有代理 
            if (!string.IsNullOrEmpty(result))
            {
                //没有"." 肯定是非IP格式
                if (result.IndexOf(".") == -1)
                {
                    result = null;
                }
                else
                {
                    //有","，估计多个代理。取第一个不是内网的IP。
                    if (result.IndexOf(",") != -1)
                    {
                        result = result.Replace(" ", string.Empty).Replace("\"", string.Empty);

                        string[] temparyip = result.Split(",;".ToCharArray());

                        if (temparyip != null && temparyip.Length > 0)
                        {
                            for (int i = 0; i < temparyip.Length; i++)
                            {
                                //找到不是内网的地址
                                if (IsIPAddress(temparyip[i])
                                    && temparyip[i].Substring(0, 3) != "10."
                                    && temparyip[i].Substring(0, 7) != "192.168"
                                    && temparyip[i].Substring(0, 7) != "172.16.")
                                {
                                    return temparyip[i];
                                }
                            }
                        }
                    }
                    //代理即是IP格式
                    else if (IsIPAddress(result))
                    {
                        return result;
                    }
                    //代理中的内容非IP
                    else
                    {
                        result = null;
                    }
                }
            }
            if (string.IsNullOrEmpty(result))
            {
                result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }

            if (string.IsNullOrEmpty(result))
            {
                result = HttpContext.Current.Request.UserHostAddress;
            }

            return result;
        }

        public static string GetAbsoluteUrl(string url)
        {
            HttpRequest request = HttpContext.Current.Request;
            if (String.IsNullOrEmpty(url))
                throw new Exception("参数url不能为空");
            url = url.ToLower();
            string[] protocols = new string[] { "http", "https" };
            foreach (string str in protocols)
            {
                if (url.StartsWith(str))
                    return url;
            }
            Uri baseUri = new Uri(request.RawUrl);
            Uri absoluteUri = new Uri(baseUri, url);
            return absoluteUri.ToString();
        }

    }
}
